import { getTimeDatePickerDistance, getTimeDistance, getTimeRangeUnit, NO_UNIT, rangePickerValueFomatter } from '@/utils/time';
import { GridContent, PageLoading } from '@ant-design/pro-layout';
import type { Moment } from 'moment';
import moment from 'moment';
import React, { Component, Suspense } from 'react';
import type { ListData } from './data';
import type { RangeValue } from 'rc-picker/lib/interface';
import styles from './style.less';
import {
  fetchAmountReceivableToday,
  fetchAmountReceivedToday,
  fetchAmountUnCollectedToday,
  fetchParkToday,
  fetchPickerChangeIn,
  fetchPickerChangeOut,
  fetchRangeParkIn,
  fetchRangeParkOut,
} from './service';

const GeneralView = React.lazy(() => import('./components/GeneralView'));
const StatisticCard = React.lazy(() => import('./components/StatisticCard'));

type DataType = 'flow_in' | 'flow_out' | 'fee' | 'space_total' | 'space_free' | 'space_occupied';


interface AnalysisState {
  rangePickerValue: [ moment.Moment, moment.Moment ];
  timeRangeChartKey: string;
  amountReceivable: number;
  amountReceived: number;
  amountUnCollected: number;
  parkNum: number;
  queryParkInList: any[];
  queryParkOutList: any[];
  loading: boolean;
}

class Analysis extends Component<any> {
  state: AnalysisState = {
    rangePickerValue: getTimeDatePickerDistance('today'),
    timeRangeChartKey: 'home',
    amountReceivable: 999, // 今日应收金额
    amountReceived: 666, // 实收金额
    amountUnCollected: 333, // 待收金额
    parkNum: 126, // 总停车数
    queryParkInList: [], // 时间跨度停车数  驶入
    queryParkOutList: [], // 驶离车次
    loading: true,
  };

  componentDidMount() {
    this.setState({
      loading: true,
    });
    // 应收金额
    fetchAmountReceivableToday().then(res => {
      this.setState({
        amountReceivable: res?.all,
      });
    });
    // 实收金额
    fetchAmountReceivedToday().then(res => {
      this.setState({
        amountReceived: res?.all,
      });
    });
    // 待收 fetchAmountUnCollectedToday
    fetchAmountUnCollectedToday().then(res => {
      this.setState({
        amountUnCollected: res?.all,
      });
    });
    // 总停车数
    fetchParkToday().then(res => {
      this.setState({
        parkNum: res?.all,
      });
    });

    const now = Date.now();
    const rangeValue = getTimeDistance('today');
    const tickRangePicker: [ moment.Moment, moment.Moment ] = [
      rangeValue[0] || moment(now).startOf('day'),
      rangeValue[1] || moment(now).endOf('day'),
    ];
    const { unit: range } = getTimeRangeUnit(tickRangePicker, [ NO_UNIT.DAY, NO_UNIT.HOUR ]);
    // 驶入
    fetchRangeParkIn({ tick: tickRangePicker, range }).then(res => {
      this.setState({
        queryParkInList: res?.allIn,
      });
    });
    // 驶离
    fetchRangeParkOut({ tick: tickRangePicker, range }).then(res => {
      this.setState({
        queryParkOutList: res?.allOut,
      });
    });

    setTimeout(() => {
      this.setState({
        loading: false,
      });
    }, 1000);
  }

  handleRangePickerChange = (rangePickerValue: RangeValue<Moment>) => {
    this.setState({
      rangePickerValue,
    });

    const now = Date.now();

    let startTime: Moment;
    let endTime: Moment;

    if (rangePickerValue) {
      startTime = rangePickerValue.at(0) || moment(now).startOf('day');

      const mom = rangePickerValue.at(1);
      if (mom) {
        endTime = mom.add(1, 'day');
      } else {
        endTime = moment(now).startOf('day').add(1, 'day');
      }
    } else {
      startTime = moment(now).startOf('day');
      endTime = moment(now).startOf('day').add(1, 'day');
    }

    const tick: [ moment.Moment, moment.Moment ] = [ startTime, endTime ];

    const { unit: range } = getTimeRangeUnit(tick, [ NO_UNIT.DAY, NO_UNIT.HOUR ]);

    // 驶入
    fetchPickerChangeIn({ tick, range }).then(res => {
      this.setState({
        queryParkInList: res?.allIn,
      });
    });
    // 驶离
    fetchPickerChangeOut({ tick, range }).then(res => {
      this.setState({
        queryParkOutList: res?.allOut,
      });
    });
  };

  selectDate = (type: 'today' | 'week' | 'month' | 'year') => {
    const rangeValue = getTimeDistance(type);

    if (type === 'today') {
      // 日历显示视图判断
      this.setState({
        rangePickerValue: getTimeDatePickerDistance('today'),
      });
    }

    if (type === 'week') {
      this.setState({
        rangePickerValue: getTimeDatePickerDistance('week'),
      });
    }
    if (type === 'month') {
      this.setState({
        rangePickerValue: getTimeDatePickerDistance('month'),
      });
    }

    if (type === 'year') {
      this.setState({
        rangePickerValue: getTimeDatePickerDistance('year'),
      });
    }
    const now = Date.now();

    const tick: [ moment.Moment, moment.Moment ] = [
      rangeValue[0] || moment(now).startOf('day'),
      rangeValue[1] || moment(now).endOf('day'),
    ];

    const { unit: range } = getTimeRangeUnit(tick, [ NO_UNIT.DAY, NO_UNIT.HOUR ]);

    // 驶入
    fetchRangeParkIn({ tick, range }).then(res => {
      this.setState({
        queryParkInList: res?.allIn,
      });
    });
    // 驶离
    fetchRangeParkOut({ tick, range }).then(res => {
      this.setState({
        queryParkOutList: res?.allOut,
      });
    });
  };

  isActive = (type: 'today' | 'week' | 'month' | 'year') => {
    const { rangePickerValue } = this.state;

    const value = getTimeDistance(type);

    if (!rangePickerValue[0] || !rangePickerValue[1]) {
      return '';
    }
    if (
      rangePickerValue[0].isSame(value[0], 'day') &&
      rangePickerValue[1].isSame(value[1], 'day')
    ) {
      return styles.currentDate;
    }
    return '';
  };

  onTimeRangeChartTabChange = (activeKey: string) => {
    this.setState({ timeRangeChartKey: activeKey });
  };

  /**
   * 数据过滤 过滤掉不在对应时间范围内的数据
   * @param data
   * @param rangePickerValue
   */
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
  public dataFilter = (data: ListData = [], rangePickerValue: RangeValue<Moment>) => {
    return data.map(item => ({
      ...item,
      tick: moment(item.collectDate),
      value: item.collectValue,
    }));
  };

  /**
   * 用于将获取到的数据转化成能够被 柱状图 组件接收的格式
   * @param data 传入的数据
   * @param rangePickerValue 限制时间跨度
   * @param keys 期望获取到的资源的键值
   * @return 键值为资源属性值为数组的对象 一个数据即对应了一个图表的数据
   */
  public timeChartDataGen(data: ListData, rangePickerValue: RangeValue<Moment>, keys: DataType[]) {
    const filtData = this.dataFilter(data, rangePickerValue);
    const expextedUnits = [ NO_UNIT.MONTH, NO_UNIT.DAY, NO_UNIT.HOUR ];
    const [ start, end ] = rangePickerValueFomatter(rangePickerValue);
    const { format } = getTimeRangeUnit([ start, end ], expextedUnits);
    const rst: Record<string, { x: string; y: number }[]> = {};
    keys.forEach(key => {
      const obj: Record<number, number> = {};
      filtData.forEach(item => {
        const tick = item.tick.format(format);
        obj[tick] = (obj[tick] || 0) + (item.value || 0);
      });
      rst[key] = Object.keys(obj).map(k => ({ x: k, y: obj[k] }));
    });
    return rst;
  }

  /**
   * 用于将获取到的数据转换成能够被 排名图 组件接收的格式
   * @param data 传入的数据
   * @param rangePickerValue 限制时间跨度
   * @param keys 期望获取到的资源的键值
   */
  public rankChartDataGen(data: ListData, rangePickerValue: RangeValue<Moment>, keys: DataType[]) {
    const filtData = this.dataFilter(data, rangePickerValue);

    const rst: Record<string, { key: string; title: string; value: number }[]> = {};

    keys.forEach(key => {
      const list: { key: string; title: string; value: number }[] = [];
      filtData.forEach(item => {
        const { zone } = item;
        const r = list.find(item2 => item2.key === zone.id);
        if (!r) list.push({ key: item.zone.id, title: item.zone.zoneName, value: item[key] || 0 });
        else r.value = (r.value || 0) + (item[key] || 0);
      });

      rst[key] = list.sort((a, b) => b.value - a.value).slice(0, 10);
    });
    return rst;
  }

  render() {
    const {
      queryParkInList,
      queryParkOutList,
      rangePickerValue,
      timeRangeChartKey,
      amountReceivable,
      amountReceived,
      amountUnCollected,
      parkNum,
    } = this.state;
    const { statisticData } = this.props;
    const keys: DataType[] = [ 'flow_in', 'flow_out' ];

    const timeInData = this.timeChartDataGen(queryParkInList, rangePickerValue, keys);
    const timeOutData = this.timeChartDataGen(queryParkOutList, rangePickerValue, keys);

    const rankData = this.rankChartDataGen(statisticData, rangePickerValue, keys);

    return (
      <GridContent>
        <React.Fragment>
          <Suspense fallback={ <PageLoading /> }>
            <GeneralView
              loading={ this.state.loading }
              data={ {
                amountReceivable,
                amountReceived,
                amountUnCollected,
                parkNum,
              } }
            />
          </Suspense>
          <Suspense fallback={ null }>
            <StatisticCard
              loading={ this.state.loading }
              isActive={ this.isActive }
              rangePickerValue={ rangePickerValue }
              handleRangePickerChange={ this.handleRangePickerChange }
              selectDate={ this.selectDate }
              activeKey={ timeRangeChartKey }
              onTabChange={ this.onTimeRangeChartTabChange }
              data={ {
                flowIn: { range: timeInData.flow_in, rank: rankData.flow_in },
                flowOut: { range: timeOutData.flow_out, rank: rankData.flow_out },
              } }
            />
          </Suspense>
        </React.Fragment>
      </GridContent>
    );
  }
}

export default Analysis;
